#[derive(Clone, Debug)]
pub enum HttpHeaderValue<'a> {

    StrVal(&'a str),

    NumberVal(usize),
}

#[derive(Clone, Debug)]
pub struct HttpHeader<'a> {

    pub name: &'a str,

    pub value: HttpHeaderValue<'a>,

}

impl<'a> HttpHeaderValue<'a> {
    
    pub fn to_string(&self) -> String {
        match self {
            HttpHeaderValue::StrVal(str) => str.to_string(),
            HttpHeaderValue::NumberVal(num) => num.to_string(),
        }
    }
}

impl<'a> HttpHeader<'a> {

    pub const fn from_str(header_name: &'a str, v: &'a str) -> HttpHeader<'a> {
        HttpHeader {
            name: header_name,
            value: HttpHeaderValue::StrVal(v),
        }
    }

    pub const fn from_num(header_name: &'a str, num: usize) -> HttpHeader<'a> {
        HttpHeader {
            name: header_name,
            value: HttpHeaderValue::NumberVal(num)
        }
    }

    pub fn get_header_value(&self) -> String {
        self.value.to_string()
    }

    pub fn to_string(&self) -> String {
        format!("{}: {}", self.name, self.get_header_value())
    }
}

impl<'a> Into<String> for HttpHeader<'a> {
    fn into(self) -> String {
        self.to_string()
    }
}

impl<'a> From<&'a str> for HttpHeader<'a> {
    fn from(value: &'a str) -> HttpHeader<'a> {
        let hkv = value.trim().split(":").filter(|x| !x.is_empty()).map(|x| x.trim()).collect::<Vec<&str>>();
        HttpHeader {
            name: hkv.get(0).unwrap(),
            value: HttpHeaderValue::StrVal(hkv.get(1).unwrap())
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::constants;

    use super::*;

    #[test]
    fn test_str_to_header() {
        let header_item = format!("{}: {}", constants::CONTENT_TYPE, constants::TEXT_HTML_CONTENT);
        let http_header: HttpHeader = HttpHeader::from(header_item.as_str());
        assert!(constants::CONTENT_TYPE.eq(http_header.name));
        assert!(constants::TEXT_HTML_CONTENT.eq(http_header.value.to_string().as_str()));
    }
}